/*
 * Copyright (c) 2015 Infosys Ltd. All rights reserved.
 */
package com.infosys.cabplanning.service.plan;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;

import javax.print.attribute.standard.Destination;

import com.google.maps.model.LatLng;
import com.infosys.cabplanning.common.Leg;
import com.infosys.cabplanning.common.Route;
import com.infosys.cabplanning.common.domain.GeoCoordidnate;
import com.infosys.cabplanning.common.domain.RelativeDistanceBean;
import com.infosys.cabplanning.helper.JsonFormatter;


import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The Class MyDistanceCalculator.
 *
 * @author Anand_Sivadas01
 * @date Feb 28, 2015
 */
@SuppressWarnings("deprecation")
public class DistanceCalculator {
	
	public static Logger LOGGER = LoggerFactory.getLogger(DistanceCalculator.class);
	
	public final static String MODE_DRIVING = "driving";

	/**
	 * The main method.
	 *
	 * @param args the arguments
	 */
	public static void main(String[] args) {
		
//		GeoCodidnates [address=Technopark Campus, Kazhakkoottam, Kerala, India, latitude=8.558095699999999, longitude=76.8807437]
//		GeoCodidnates [address=Infosys Phase II, Kulathoor, Thiruvananthapuram, Kerala 695582, India, latitude=8.533265999999999, longitude=76.88353599999999]
		LatLng fromPosition = new LatLng(8.558095699999999, 76.8807437);
		LatLng toPosition = new LatLng(8.533265999999999, 76.88353599999999);
		
		//http://maps.googleapis.com/maps/api/directions/json?origin=8.558095699999999,76.8807437&destination=8.533265999999999,76.88353599999999&sensor=false&units=metric&mode=driving
		String url = "http://maps.googleapis.com/maps/api/directions/json?" 
            + "origin=" + fromPosition.lat + "," + fromPosition.lng  
            + "&destination=" + toPosition.lat + "," + toPosition.lng 
            + "&sensor=false&units=metric&mode="+MODE_DRIVING;

		try {
		HttpClient httpClient = new DefaultHttpClient();
        HttpContext localContext = new BasicHttpContext();
        HttpPost httpPost = new HttpPost(url);
        HttpResponse response  = httpClient.execute(httpPost, localContext);
		InputStream inputStream = response.getEntity().getContent();
		StringWriter stringWriter = new StringWriter();
		IOUtils.copy(inputStream, stringWriter, "UTF-8");
		String theString = stringWriter.toString();
		System.out.println(theString);
		} catch (ClientProtocolException clientProtocolException) {
			LOGGER.error("ClientProtocolException while invoking Google Directions API: ", clientProtocolException);
		} catch (IOException ioException) {
			LOGGER.error("IOException while invoking Google Directions API: ", ioException);
		}
	}
	
	/**
	 * Gets the distance between coordinates.
	 *
	 * @param startPoint the start point
	 * @param destinationPoint the destination point
	 * @return the distance between coordinates
	 */
	public static String getDistanceBetweenCoordinates(GeoCoordidnate startPoint, GeoCoordidnate destinationPoint) {
		
		String directionJSONString = null;
		LatLng fromPosition = new LatLng(startPoint.getLatitude().doubleValue(), startPoint.getLongitude().doubleValue());
		LatLng toPosition = new LatLng(destinationPoint.getLatitude().doubleValue(), destinationPoint.getLongitude().doubleValue());
		try {
			directionJSONString = queryGoogleDirectionsAPI(fromPosition, toPosition);
			
		} catch (ClientProtocolException clientProtocolException) {
			LOGGER.error("ClientProtocolException while invoking Google Directions API: ", clientProtocolException);
		} catch (IOException ioException) {
			LOGGER.error("IOException while invoking Google Directions API: ", ioException);
		}
		
		return directionJSONString;
	}
	
	public static RelativeDistanceBean distanceDomain(String jsonString) {
		// TODO provide implementation to get the distance and time taken
		
		JSONObject jObject = new JSONObject(jsonString);
		Route routeDTO = new JsonFormatter().parse(jObject);
		Leg leg = routeDTO.getRoutes().get(0).getLegs().get(0);
		Integer distanceInMeters = leg.getDistance().getValue();
		Integer durationInSeconds = leg.getDuration().getValue();
		
		RelativeDistanceBean relativeDistanceBean = new RelativeDistanceBean();
		relativeDistanceBean.setDistance(distanceInMeters);
		relativeDistanceBean.setTime(durationInSeconds);
		
		return relativeDistanceBean;
	}
	
	/**
	 * Query google directions api.
	 *
	 * @param fromPosition the from position
	 * @param toPosition the to position
	 * @return the string
	 * @throws ClientProtocolException the client protocol exception
	 * @throws IOException Signals that an I/O exception has occurred.
	 */
	private static String queryGoogleDirectionsAPI(LatLng fromPosition, LatLng toPosition) throws ClientProtocolException, IOException {
		
		String url = "http://maps.googleapis.com/maps/api/directions/json?" 
            + "origin=" + fromPosition.lat + "," + fromPosition.lng  
            + "&destination=" + toPosition.lat + "," + toPosition.lng 
            + "&sensor=false&units=metric&mode="+MODE_DRIVING;

		HttpClient httpClient = new DefaultHttpClient();
        HttpContext localContext = new BasicHttpContext();
        HttpPost httpPost = new HttpPost(url);
        HttpResponse response  = httpClient.execute(httpPost, localContext);
		InputStream inputStream = response.getEntity().getContent();
		StringWriter stringWriter = new StringWriter();
		IOUtils.copy(inputStream, stringWriter, "UTF-8");
		String directionJSON = stringWriter.toString();
		
		return directionJSON;
	}

}
